from flask import Flask, Response, render_template_string, request, redirect, url_for
import cv2
import time
import logging
import atexit
import threading
from picamera2 import Picamera2

# — 日志设置 — #
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s - %(message)s')

# — 默认配置 — #
DEFAULT_RESOLUTIONS = [(640, 480), (800, 600), (1280, 720), (1920, 1080)]
DEFAULT_FPS_LIST    = [5, 10, 15, 24, 30, 60]

config = {
    "size": DEFAULT_RESOLUTIONS[0],
    "fps": DEFAULT_FPS_LIST[1],  # 10 fps
    "controls": {
        "Brightness": 1.0,
        "Contrast": 1.0,
        "ExposureTime": 10000,
    }
}

camera = Picamera2()
camera_lock = threading.Lock()

def configure_camera():
    """使用 create_video_configuration 保证输出正常画面"""
    with camera_lock:
        try:
            camera.stop()
        except Exception:
            pass

        # 和你提供的“工作”版本保持一致
        video_config = camera.create_video_configuration(main={"size": config["size"]})
        camera.configure(video_config)
        camera.set_controls(config["controls"])
        camera.start()
        logging.info(f"Camera configured: size={config['size']} fps={config['fps']} controls={config['controls']}")

# 初始启动
configure_camera()
atexit.register(lambda: (camera.stop(), logging.info("Camera stopped.")))

def generate_frames():
    interval = 1.0 / config["fps"]
    while True:
        start = time.time()
        try:
            frame = camera.capture_array()
            ret, buffer = cv2.imencode('.jpg', frame)
            if ret:
                yield (b'--frame\r\n'
                       b'Content-Type: image/jpeg\r\n\r\n' +
                       buffer.tobytes() + b'\r\n')
        except Exception as e:
            logging.error(f"Frame error: {e}", exc_info=True)
            break
        elapsed = time.time() - start
        if elapsed < interval:
            time.sleep(interval - elapsed)

app = Flask(__name__)

# — 首页 — #
@app.route('/')
def index():
    return render_template_string("""
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <script src="https://cdn.tailwindcss.com"></script>
        <title>实时视频流</title>
    </head>
    <body class="bg-gray-100 text-gray-800">
        <div class="max-w-screen-md mx-auto py-8">
            <h1 class="text-3xl font-bold mb-4">📷 实时视频流</h1>
            <img src="{{ url_for('video_feed') }}" class="border rounded shadow mb-4" />
            <a href="{{ url_for('settings') }}"
               class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
               ⚙️ 设置相机参数
            </a>
        </div>
    </body>
    </html>
    """)

# — 视频流接口 — #
@app.route('/video_feed')
def video_feed():
    headers = {'Cache-Control': 'no-cache, no-store, must-revalidate'}
    return Response(
        generate_frames(),
        mimetype='multipart/x-mixed-replace; boundary=frame',
        headers=headers
    )

# — 设置页 — #
@app.route('/settings', methods=['GET', 'POST'])
def settings():
    if request.method == 'POST':
        # 读取表单并更新配置
        w, h = map(int, request.form['resolution'].split('x'))
        config['size'] = (w, h)
        config['fps'] = float(request.form['fps'])
        config['controls']['Brightness'] = float(request.form['brightness'])
        config['controls']['Contrast'] = float(request.form['contrast'])
        config['controls']['ExposureTime'] = int(request.form['exposure_time'])
        configure_camera()
        return redirect(url_for('settings'))

    return render_template_string("""
    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <script src="https://cdn.tailwindcss.com"></script>
        <title>相机设置</title>
    </head>
    <body class="bg-white text-gray-800">
        <div class="max-w-screen-md mx-auto py-10 px-4">
            <h1 class="text-2xl font-bold mb-6">⚙️ 设置相机参数</h1>
            <form method="post" class="space-y-4">
                <div>
                    <label class="block font-medium">分辨率：</label>
                    <select name="resolution" class="w-full border p-2 rounded">
                        {% for w, h in resolutions %}
                            <option value="{{w}}x{{h}}" {% if size == (w, h) %}selected{% endif %}>
                                {{w}} x {{h}}
                            </option>
                        {% endfor %}
                    </select>
                </div>
                <div>
                    <label class="block font-medium">输出帧率：</label>
                    <select name="fps" class="w-full border p-2 rounded">
                        {% for f in fps_list %}
                            <option value="{{f}}" {% if f == fps %}selected{% endif %}>{{f}} fps</option>
                        {% endfor %}
                    </select>
                </div>
                <div>
                    <label class="block font-medium">亮度：</label>
                    <input type="number" step="0.1" min="0" max="4" name="brightness"
                           class="w-full border p-2 rounded" value="{{controls.Brightness}}">
                </div>
                <div>
                    <label class="block font-medium">对比度：</label>
                    <input type="number" step="0.1" min="0" max="4" name="contrast"
                           class="w-full border p-2 rounded" value="{{controls.Contrast}}">
                </div>
                <div>
                    <label class="block font-medium">曝光时间（μs）：</label>
                    <input type="number" name="exposure_time"
                           class="w-full border p-2 rounded" value="{{controls.ExposureTime}}">
                </div>
                <div class="pt-4">
                    <button type="submit" class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700">
                        ✅ 应用设置
                    </button>
                    <a href="{{ url_for('index') }}" class="ml-4 text-blue-600 underline">返回首页</a>
                </div>
            </form>
        </div>
    </body>
    </html>
    """,
    size=config['size'],
    fps=config['fps'],
    controls=config['controls'],
    resolutions=DEFAULT_RESOLUTIONS,
    fps_list=DEFAULT_FPS_LIST)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, threaded=True)
